package src

import (
	"errors"
	"fmt"

	"encoding/gob"
	"strconv"
	"strings"

	. "xwaf_admin/xadmin/src/lib"
	m "xwaf_admin/xadmin/src/models"

	beego "github.com/beego/beego/v2/server/web"
	"github.com/beego/beego/v2/server/web/context"
)

var accesslist = make(map[string]bool)

func init() {
	gob.Register(accesslist)
}

//check access and register user's nodes
func AccessRegister() {
	var Check = func(ctx *context.Context) {
		authType, _ := beego.AppConfig.String("user_auth_type")
		user_auth_type, _ := strconv.Atoi(authType)
		rbac_auth_gateway, _ := beego.AppConfig.String("rbac_auth_gateway")
		var accesslist map[string]bool
		if user_auth_type > 0 {
			params := strings.Split(strings.ToLower(strings.Split(ctx.Request.RequestURI, "?")[0]), "/")
			if CheckAccess(params) {
				uinfo := ctx.Input.Session("userinfo")
				//fmt.Println(uinfo)
				if uinfo == nil {
					ctx.Redirect(302, rbac_auth_gateway)
					fmt.Println(uinfo)
					return
				}
				//admin用户不用认证权限
				adminuser, _ := beego.AppConfig.String("rbac_admin_user")
				var rolelist []string
				for _, vv := range uinfo.(m.User).Role {
					rolelist = append(rolelist, vv.Name)
				}
				if uinfo.(m.User).Username == adminuser || strings.Contains(strings.Join(rolelist, ","), "超级管理员") {
					return
				}

				if user_auth_type == 1 {
					listbysession := ctx.Input.Session("accesslist")
					if listbysession != nil {
						accesslist = listbysession.(map[string]bool)
					}

				} else if user_auth_type == 2 {
					accesslist, _ = GetAccessList(uinfo.(m.User).Id)
				}
				ret := AccessDecision(params, accesslist)
				if !ret {
					ctx.Output.JSON(&map[string]interface{}{"code": -1, "msg": "模块权限不足"}, true, false)
				}
			}

		}
	}
	beego.InsertFilter("/*", beego.BeforeRouter, Check)
}

//Determine whether need to verify
func CheckAccess(params []string) bool {
	if len(params) < 3 {
		return false
	}
	authType, _ := beego.AppConfig.String("not_auth_package")
	for _, nap := range strings.Split(authType, ",") {
		if params[1] == nap {
			return false
		}
	}
	return true
}

//To test whether permissions
func AccessDecision(params []string, accesslist map[string]bool) bool {
	if CheckAccess(params) {
		//fmt.Println(params)
		paramsLength := len(params)
		s := fmt.Sprintf("%s", params[1])
		if paramsLength == 3 {
			s = fmt.Sprintf("%s/%s", params[1], params[2])
		} else if paramsLength == 4 {
			s = fmt.Sprintf("%s/%s/%s", params[1], params[2], params[3])
		} else if paramsLength == 5 {
			s = fmt.Sprintf("%s/%s/%s/%s", params[1], params[2], params[3], params[4])
		}

		if len(accesslist) < 1 {
			return false
		}
		_, ok := accesslist[s]
		if ok != false {
			return true
		}
	} else {
		return true
	}
	return false
}

type AccessNode struct {
	Id        int64
	Name      string
	Childrens []*AccessNode
}

//Access permissions list
func GetAccessList(uid int64) (map[string]bool, error) {
	list, err := m.AccessList(uid)
	if err != nil {
		return nil, err
	}
	alist := make([]*AccessNode, 0)
	for _, l := range list {
		if l["Pid"].(int64) == 0 && l["Level"].(int64) == 1 {
			anode := new(AccessNode)
			anode.Id = l["Id"].(int64)
			anode.Name = l["Name"].(string)
			alist = append(alist, anode)
		}
	}
	for _, l := range list {
		if l["Level"].(int64) == 2 {
			for _, an := range alist {
				if an.Id == l["Pid"].(int64) {
					anode := new(AccessNode)
					anode.Id = l["Id"].(int64)
					anode.Name = l["Name"].(string)
					an.Childrens = append(an.Childrens, anode)
				}
			}
		}
	}
	for _, l := range list {
		if l["Level"].(int64) == 3 {
			for _, an := range alist {
				for _, an1 := range an.Childrens {
					if an1.Id == l["Pid"].(int64) {
						anode := new(AccessNode)
						anode.Id = l["Id"].(int64)
						anode.Name = l["Name"].(string)
						an1.Childrens = append(an1.Childrens, anode)
					}
				}

			}
		}
	}
	//accesslist := make(map[string]bool)
	for _, v := range alist {
		for _, v1 := range v.Childrens { //针对只有二级目录结构的
			if len(v1.Childrens) == 0 {
				vname := strings.Split(v.Name, "/")
				str := fmt.Sprintf("%s/%s", strings.ToLower(vname[0]), strings.ToLower(v1.Name))
				accesslist[str] = true
			} else {
				for _, v2 := range v1.Childrens {
					vname := strings.Split(v.Name, "/")
					v1name := strings.Split(v1.Name, "/")
					//v2name := strings.Split(v2.Name, "/")
					//log.Println(v2.Name)
					//str := fmt.Sprintf("%s/%s/%s", strings.ToLower(vname[0]), strings.ToLower(v1name[0]), strings.ToLower(v2name[0]))
					str := fmt.Sprintf("%s/%s/%s", strings.ToLower(vname[0]), strings.ToLower(v1name[0]), strings.ToLower(v2.Name))

					accesslist[str] = true
				}
			}
		}
	}
	return accesslist, nil
}

//check login
func CheckLogin(username string, password string) (user m.User, err error) {
	user, err = m.GetUserByUsername(username)
	if err != nil {
		return user, err
	}
	if user.Id == 0 {
		return user, errors.New("用户不存在")
	}
	if user.Password != Pwdhash(password) {
		return user, errors.New("密码错误")
	}
	return user, nil
}
